package com.wonder.app.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.utils.VtuzxUtil;
import com.wonder.admin.service.IVtuzxKingdeeService;
import com.wonder.app.domain.*;
import com.wonder.app.mapper.*;
import com.wonder.app.request.PickDetailRequest;
import com.wonder.app.request.PrdPickRequest;
import com.wonder.app.request.SfcProplanRequest;
import com.wonder.app.service.*;
import com.wonder.bean.kingdee.VtuzxKingdeeCloudClient;
import com.wonder.bean.kingdee.xqc.VtuzxArrayList;
import com.wonder.common.utils.DateUtils;
import com.wonder.common.utils.MapToEntity;
import com.wonder.constant.BillType;
import com.wonder.constant.IXqcConst;
//import cpcl.PrinterHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class PrdPickServiceImpl extends ServiceImpl<PrdPickDao, PrdPick> implements PrdPickService {

    private static final Logger _logger = LoggerFactory.getLogger(PrdPickServiceImpl.class);

    @Autowired
    private  PrdPickDao prdPickDao;

    @Autowired
    private  PrdPickService prdPickService;

    @Autowired
    private PickDetailDao pickDetailDao;

    @Autowired
    private TrayDao trayDao;

    @Autowired
    private PickDetailService pickDetailService;

    @Autowired
    private  IVtuzxKingdeeService kingdeeService;

    @Autowired
    private SyncKingdeeOrderService syncKingdeeOrderService;

    @Autowired
    private TrayService trayService;

    @Autowired
    private SfcproplanDetailDao sfcproplanDetailDao;

    @Autowired
    private SfcProplanDao sfcProplanDao;

    @Autowired
    private PrdFeedDetailService prdFeedDetailService;

    @Autowired
    private PrdIronTrayService prdIronTrayService;

    @Autowired
    private PpBomDao ppBomDao;

    @Autowired
    private PpBomService ppBomService;

    @Autowired
    private OccupyDao occupyDao;
    @Autowired
    private OccupyService occupyService;
    @Autowired
    private SyncKingdeeOrderService syncKingdeeOrderServicel;

    @Override
    public IPage<PrdPick> selectList(PrdPickRequest request, Page<PrdPick> page) {
//        LambdaQueryWrapper<PrdPick> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//
//        if (request.getBillNo() != null){
//            lambdaQueryWrapper.like(PrdPick::getFBILLNO,request.getBillNo());
//        }
//        if (request.getFKDBILLNO() != null){
//            lambdaQueryWrapper.like(PrdPick::getFKDBILLNO,request.getFKDBILLNO());
//        }
//
//        if (request.getFCREATEUSER() != null){
//            lambdaQueryWrapper.like(PrdPick::getFCREATEUSER,request.getFCREATEUSER());
//        }
//        if (request.getFBILLNOMO() != null){
//            lambdaQueryWrapper.like(PrdPick::getFBILLNOMO,request.getFBILLNOMO());
//        }
//        if (request.getFWORKSHOPNAME() != null){
//            lambdaQueryWrapper.like(PrdPick::getFWORKSHOPNAME,request.getFWORKSHOPNAME());
//        }
//        if (request.getJoinMaterialName() != null){
//            lambdaQueryWrapper.like(PrdPick::getJoinMaterialName,request.getJoinMaterialName());
//        }
//
//        if (null != request.getTRAYNO()) {
//            String trayNo = request.getTRAYNO().replace("'", "''"); // 防注入
//            lambdaQueryWrapper.inSql(PrdPick::getFBILLNO,
//                    "SELECT BillNo FROM t_prd_pick_detail WHERE TrayNo = '" + trayNo + "'");
//        }
//        if (request.getFDATE() != null){
//            Date[] orderDate = request.getFDATE();
//            if(orderDate.length>0)
//                lambdaQueryWrapper.ge(PrdPick::getFDATE, orderDate[0]);
//            if(orderDate.length==2)
//                lambdaQueryWrapper.le(PrdPick::getFDATE,orderDate[1]);
//
//        }
//        lambdaQueryWrapper.orderByDesc(PrdPick::getFDATE);
//        Page<PrdPick> selectPage = this.baseMapper.selectPage(page, lambdaQueryWrapper);
        Page<PrdPick> result = prdPickDao.selectPickAndDetail(page,request);
        return result;
    }

    /**
     * 验证生产领料信息
     *
     * @param prdPick
     * @param type
     * @return String
     */
    @Override
    public String validate(PrdPick prdPick,String type){


        return "";
    }



    /**
     * 创建生产领料单
     * @param userName
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createPickBill(Long userId,String userName, Map<String, Object> map) throws Exception {
        Map<String,Object> planData = VtuzxUtil.getObject(map,"planData");
        List<Map<String,Object>> detailList = VtuzxUtil.getObject(map,"detail");
        String PickBillNo =  IXqcConst.createBillNo(BillType.SCLL);//生成中台领料单号
        String inStockTime =  VtuzxUtil.getString(map,"inStockTime");//单据日期
        String FBILLNOMO = VtuzxUtil.getString(map,"moBillNo");//生产订单号
        String BIllNo = VtuzxUtil.getString(map,"billNo");//工序计划单号
        //获取车间信息
        List<SfcproplanDetail> sfcproplanDetailList = sfcproplanDetailDao.selectList(new LambdaQueryWrapper<SfcproplanDetail>()
                .eq(SfcproplanDetail::getBillNo, BIllNo));
        String workNo = "";
        String workName = "";
        if(!VtuzxUtil.isEmpty(sfcproplanDetailList)){
            workName = sfcproplanDetailList.get(0).getDepartName();
            workNo = sfcproplanDetailList.get(0).getDepartNo();

        }
        List<String> trayList = new ArrayList<>();//托号集合

        List<PickDetail> pickDetailList = new ArrayList<>();
        for (Map<String,Object> data : detailList ){
            PickDetail pickDetail = MapToEntity.mapToBean(data,PickDetail.class);
            pickDetail.setTEMP(false);
            pickDetail.setFBILLNO(PickBillNo);//领料单号
            pickDetail.setISPRINT(false);//是否打印
            pickDetail.setWORKSHOPNAME(workName);//车间名称
            String trayno = pickDetail.getTRAYNO();
            if (!trayList.contains(trayno)){
                trayList.add(trayno);
            }
            pickDetailList.add(pickDetail);
        }
        PrdPick pick = new PrdPick();
        pick.setFBILLNO(PickBillNo);
        pick.setFDATE(DateUtils.strToDate(inStockTime,"yyyy-MM-dd"));
        pick.setCreateTime(new Date());
        pick.setFCREATEUSER(userName);
        pick.setFSTATE(false);
        pick.setFBILLNOMO(FBILLNOMO);//生产订单单号
        pick.setFWORKSHOPNO(workNo);//车间编码
        pick.setFWORKSHOPNAME(workName);//车间名称


        //机加车间传金蝶领料单，毛坯车间传金蝶调拨单
        if (workName.contains("机加")){
            try {
                syncKingdeeOrderService.syncPrdPick(userId,pick,pickDetailList);
            } catch (Exception e){
//                _logger.info(e.getMessage());
                if (e.getMessage().contains("更新库存不成功")){
                    throw new RuntimeException("库存不足,请确认托码是否质检入库");
                }
                throw new RuntimeException(e.getMessage());
            }
        } else {//传调拨单
            try {
                syncKingdeeOrderService.syncAllocation(userId,pick,pickDetailList);
            } catch (Exception e){
                if (e.getMessage().contains("更新库存不成功")){
                    throw new RuntimeException("库存不足,请确认托码是否质检入库");
                }
                throw new RuntimeException(e.getMessage());
            }
        }


        //保存到数据库
        boolean savehead = prdPickService.save(pick);
        boolean saveBatch = pickDetailService.saveOrUpdateBatch(pickDetailList);
        Boolean aBoolean = updateTrayMaterial(trayList, BIllNo);



        return savehead && saveBatch;

    }


    /**
     * 机加领料后修改托盘上的物料信息
     * @return
     */
    private Boolean updateTrayMaterial(List<String> trayList,String operNo){
        SfcProplan sfcProplan = sfcProplanDao.selectOne(new LambdaQueryWrapper<SfcProplan>()
                .eq(SfcProplan::getBillNo, operNo));
        List<Tray> trays = trayDao.selectList(new LambdaQueryWrapper<Tray>()
                .in(Tray::getFBILLNO, trayList));
        List<String> ironNoList = new ArrayList<>();
        for (Tray tray : trays){
            tray.setFMATERIALNAME(sfcProplan.getMaterialName());
            tray.setFMATERIALNUMBER(sfcProplan.getMaterialNo());
            tray.setFSPECIFICATION(sfcProplan.getSpecification());
            tray.setFUNITNAME(sfcProplan.getUnitName());
            tray.setFUNITID(sfcProplan.getUnitNo());
            tray.setITEMNUMBER(sfcProplan.getSpecification());
            tray.setISSOURCE(false);
            String ironno = tray.getIRONNO();
            if (!ironNoList.contains(ironno)){
                ironNoList.add(ironno);
            }
        }

        boolean res = trayService.saveOrUpdateBatch(trays);

//        prdIronTrayService.update(null, Wrappers
//                .<PrdIronTray>lambdaUpdate()
//                .in(PrdIronTray::getBillNo,ironNoList)
//                .set(PrdIronTray::getStatus,false));
        //修改铁托的状态为可以使用
        return res;
    }

    /**
     * 创建领料单详情临时数据
     * @param userName
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createPickDetailTemp(String userName, Map<String, Object> map) throws Exception {
        Map<String,Object> trayData = VtuzxUtil.getObject(map,"trayData");//托盘信息
        Map<String,Object> planData = VtuzxUtil.getObject(map,"planData");//工序计划信息
        //判断是走领料还是补料
        String type = VtuzxUtil.getString(map,"type");
        String billNo = VtuzxUtil.getString(planData,"billNo");


        String materialNo = VtuzxUtil.getString(trayData,"fmaterialnumber");
        String materialName = VtuzxUtil.getString(trayData,"fmaterialname");
        String specification = VtuzxUtil.getString(trayData,"fspecification");//规格
        String funitid = VtuzxUtil.getString(trayData,"funitid");//单位内码
        String funitname = VtuzxUtil.getString(trayData,"funitid");//单位名称
        String flot = VtuzxUtil.getString(trayData,"flot");//批号
        String trayNo = VtuzxUtil.getString(trayData,"fbillno");//托盘编号
        String foperpno = VtuzxUtil.getString(trayData,"foperpno");//工单号
        String instocktime = VtuzxUtil.getString(trayData,"instocktime");//工单号
        if(!VtuzxUtil.isEmpty(foperpno)){
            throw new RuntimeException(String.format("托盘已经绑定工单号:%s,无法重复绑定",foperpno));
        }
        boolean isPpbom = VtuzxUtil.getBoolean(trayData,"isPpBom");//是否是用料清单上的物料
        double fqty = VtuzxUtil.getDouble(trayData,"fqty");//领料数量

        String moBillNo = VtuzxUtil.getString(planData,"moBillNo");//生产订单单号

        boolean save = false;
        if ("pick".equals(type)){
            //需要校验领取的数量是否大于剩余未发数量
            PpBom ppBom = ppBomDao.selectOne(new LambdaQueryWrapper<PpBom>()
                    .eq(PpBom::getFMOBILLNO, moBillNo)
                    .eq(PpBom::getFMATERIALNUMBER, materialNo));
            Double fresidueqty = ppBom.getFRESIDUEQTY();//剩余未发数量
            if (fqty > fresidueqty){
                throw new RuntimeException(String.format("领料数量大于剩余未发数量,剩余未发数量为:%.2f",fresidueqty));
            }

            PickDetail pickDetail = new PickDetail();
            pickDetail.setFMATERIALNUMBER(materialNo);
            pickDetail.setFMATERIALNAME(materialName);
            pickDetail.setFSPECIFICATION(specification);
            pickDetail.setFUNITNAME(funitname);
            pickDetail.setFUNITID(funitid);
            pickDetail.setFINFACTQTY(fqty);//领料数量
            pickDetail.setFLOT(flot);
            pickDetail.setTRAYNO(trayNo);
            pickDetail.setTEMP(true);
            pickDetail.setMOBILLNO(moBillNo);
            pickDetail.setCREATETIME(new Date());
            pickDetail.setISPPBOM(isPpbom);

            save = pickDetailService.save(pickDetail);
            //修改bom中的剩余未发数和领料数
            ppBom.setFRESIDUEQTY(fresidueqty - fqty);//剩余未发数(当前剩余未发数 - 领料数)
            ppBom.setFINFACTQTY(ppBom.getFINFACTQTY() + fqty);//实发数量(当前实发数 + 领料数)
            ppBomService.updateById(ppBom);

        }
//        else {
//            PrdFeedDetail prdFeedDetail = new PrdFeedDetail();
//            prdFeedDetail.setFMATERIALNUMBER(materialNo);
//            prdFeedDetail.setFMATERIALNAME(materialName);
//            prdFeedDetail.setFSPECIFICATION(specification);
//            prdFeedDetail.setFUNITNAME(funitname);
//            prdFeedDetail.setFUNITID(funitid);
//            prdFeedDetail.setFACTUALQTY(fqty);//实发数量
//            prdFeedDetail.setFLOT(flot);
//            prdFeedDetail.setTRAYNO(trayNo);
//            prdFeedDetail.setTEMP(true);
//            prdFeedDetail.setMOBILLNO(moBillNo);
//            prdFeedDetail.setCREATETIME(new Date());
//            prdFeedDetail.setISPPBOM(isPpbom);
//            save = prdFeedDetailService.save(prdFeedDetail);
//        }

        //先调用托盘出库的方法
        try {
//            trayService.updateTray(trayData);
            //托盘绑定工单号并且打印出工单二维码
            trayService.bandingOperp(trayData,billNo,moBillNo);
        } catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }


        return save;
    }

    /**
     * 删除领料中的临时数据
     * @param userName
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Boolean deletePickDetailTemp(String userName, Map<String, Object> map) throws Exception {
        String moBillNo = VtuzxUtil.getString(map,"moBillNo");
        Map<String,Object> pickDetail = VtuzxUtil.getObject(map,"pickDetail");
        String trayNo = VtuzxUtil.getString(pickDetail,"trayno");
        int detailId = VtuzxUtil.getInt(pickDetail,"id");
        String materialNo = VtuzxUtil.getString(pickDetail,"fmaterialnumber");
        double count = VtuzxUtil.getDouble(pickDetail,"finfactqty");//数量
        //托盘数量放回去
        //先调用托盘出库的方法
//        try {
//            trayService.addTray(pickDetail,"pick");
//        } catch (Exception e){
//            throw new RuntimeException(e.getMessage());
//        }
        //将工单号删除
        Map<String,Object> trayData = new HashMap<>();
        trayData.put("fbillno",trayNo);
        try {
            trayService.bandingOperp(trayData,"","");
        } catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
        //修改bom中的剩余未发数量和实发数量
        PpBom ppBom = ppBomDao.selectOne(new LambdaQueryWrapper<PpBom>()
                .eq(PpBom::getFMOBILLNO, moBillNo)
                .eq(PpBom::getFMATERIALNUMBER, materialNo));
        Double fresidueqty = ppBom.getFRESIDUEQTY();//剩余未发数量
        //修改bom中的剩余未发数和领料数
        ppBom.setFRESIDUEQTY(fresidueqty + count);//剩余未发数(当前剩余未发数 + 领料数)
        ppBom.setFINFACTQTY(ppBom.getFINFACTQTY() - count);//实发数量(当前实发数 - 领料数)
        ppBomService.updateById(ppBom);
        //删除临时表中的数据
        boolean b = pickDetailService.removeById(detailId);
        return b;
    }

    /**
     * 包装间生成领料单
     * @param userName
     * @param
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createPickBillPackage(Long user_id, String userName,SfcOptrptPackage sfcOptrptPackage) throws Exception {

        List<PickDetail> pickDetailList = new ArrayList<>();
        String PickBillNo =  IXqcConst.createBillNo(BillType.SCLL);//生成中台领料单号
        String FBILLNOMO = sfcOptrptPackage.getMoBillNo();//生产订单号
        double qty = sfcOptrptPackage.getQuaQty();//合格数量
        //车间都是包装车间

        PickDetail pickDetail = new PickDetail();
        //需要查询出领料的物料信息,只要机加成品即可(物料编码0201开头)
        PpBom ppBom = ppBomDao.selectOne(new LambdaQueryWrapper<PpBom>()
                .eq(PpBom::getFMOBILLNO, FBILLNOMO)
                .like(PpBom::getFMATERIALNUMBER, sfcOptrptPackage.getMaterialNo()));

        pickDetail.setFMATERIALNUMBER(ppBom.getFMATERIALNUMBER());
        pickDetail.setFMATERIALNAME(ppBom.getFMATERIALNAME());
        pickDetail.setFSPECIFICATION(ppBom.getFSPECIFICATION());
        pickDetail.setFUNITNAME(ppBom.getFUNITNAME());
        pickDetail.setFUNITID(ppBom.getFUNITID());
        pickDetail.setFINFACTQTY(qty);//领料数量为汇报的合格数量
        pickDetail.setFLOT("");
        pickDetail.setTRAYNO("");
        pickDetail.setTEMP(true);
        pickDetail.setMOBILLNO(FBILLNOMO);
        pickDetail.setCREATETIME(new Date());
        pickDetail.setISPPBOM(true);
        pickDetail.setFBILLNO(PickBillNo);//领料单号
        pickDetail.setFSTOCKNUMBER("CK020");//仓库编码
        pickDetail.setFSTOCKNAME("包装材料库");//仓库名称
        pickDetailList.add(pickDetail);

        PrdPick pick = new PrdPick();
        pick.setFBILLNO(PickBillNo);
        pick.setFDATE(new Date());
        pick.setFCREATEUSER(userName);
        pick.setFSTATE(false);
        pick.setFBILLNOMO(FBILLNOMO);//生产订单单号
        pick.setFWORKSHOPNO("BZ");//车间编码
        pick.setFWORKSHOPNAME("包装车间");//车间名称
//            pickList.add(pick);
        prdPickService.saveOrUpdate(pick);
        pickDetailService.saveOrUpdate(pickDetail);
        //传金蝶领料单
        try {
            syncKingdeeOrderService.syncPrdPickBao(user_id,pick,pickDetailList,sfcOptrptPackage);
        } catch (Exception e){
            throw new RuntimeException(e.getMessage());

        }



        return true;
    }

    /**
     * 机加车间还没有打印的托盘
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getJijiaTray(Map<String, Object> map) throws Exception {
        String billNo = VtuzxUtil.getString(map,"billNo");//托盘号
        LambdaQueryWrapper<PickDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PickDetail::getISPRINT, false)
                .eq(PickDetail::getWORKSHOPNAME, "机加车间")
                .ne(PickDetail::getTEMP, true)
                .orderByDesc(PickDetail::getCREATETIME);//不是临时数据
        if (!VtuzxUtil.isEmpty(billNo)){
            queryWrapper.like(PickDetail::getTRAYNO,billNo);
        }
        List<PickDetail> pickDetailList = pickDetailDao.selectList(queryWrapper);
        if(!VtuzxUtil.isEmpty(pickDetailList)){
            List<String> trayList = pickDetailList.stream()//托号集合
                    .map(PickDetail::getTRAYNO)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            List<Tray> trays = trayDao.selectList(new LambdaQueryWrapper<Tray>()
                    .in(Tray::getFBILLNO, trayList));
            Map<String,Object> trayMap = new HashMap<>();//key 托号 val :件号
            for (Tray tray : trays){
                String itemnumber = tray.getITEMNUMBER();
                String fbillno = tray.getFBILLNO();
                trayMap.put(fbillno,itemnumber);
            }
            for (PickDetail pickDetail : pickDetailList ){
                String itemnumber = VtuzxUtil.getString(trayMap,pickDetail.getTRAYNO());
                pickDetail.setFSPECIFICATION(itemnumber);
            }
        }


        Map<String,Object> data = new HashMap<>();
        data.put("dataList",pickDetailList);

        return data;
    }

    /**
     * 修改机加车间托盘打印的状态
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Boolean updateJijiaTray(Map<String, Object> map) throws Exception {
        int detailId = VtuzxUtil.getInt(map,"id");
        PickDetail pickDetail = pickDetailDao.selectById(detailId);
        pickDetail.setISPRINT(true);
        boolean b = pickDetailService.updateById(pickDetail);
        return b;
    }

    /**
     * 修改机加托盘打印状态为未打印
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Boolean updatePrint(String userName,Map<String, Object> map) throws Exception {
        int detailId = VtuzxUtil.getInt(map,"id");
        PickDetail pickDetail = pickDetailDao.selectById(detailId);
        _logger.info(String.format("%s修改托盘:%s的打印状态",userName,pickDetail.getTRAYNO()));
        pickDetail.setISPRINT(false);
        boolean b = pickDetailService.updateById(pickDetail);
        return b;
    }

    /**
     * 查询领料详情列表(用于机加调整托盘打印)
     * @param detailRequest
     * @param page
     * @return
     * @throws Exception
     */
    @Override
    public IPage<PickDetail> selectDetailList(PickDetailRequest detailRequest, Page<PickDetail> page) throws Exception {

        Page<PickDetail> selectPage = pickDetailDao.selectPageAndTray(page, detailRequest);
        return selectPage;
    }


    /**
     * 生产领料明细详情
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getPrdPickDetail(Map<String, Object> map) {
        String billNo = map.get("billNo").toString();
        PrdPick prdPickform = prdPickDao.selectOne(new LambdaQueryWrapper<PrdPick>()
                .eq(PrdPick::getFBILLNO,billNo));
        List<PickDetail> prdPickdetailList = pickDetailDao.selectList(new LambdaQueryWrapper<PickDetail>()
                .eq(PickDetail::getFBILLNO,billNo));
        Map<String,Object> data = new HashMap<>();
        data.put("data",prdPickform);
        data.put("dataList",prdPickdetailList);
        return data;
    }

}
